/*
 * Teknei 2014 - All rights reserved
 */
package com.teknei.acabus.core.singleton;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Startup;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.teknei.acabus.FacadeException;
import com.teknei.acabus.core.entities.NavigationChild;
import com.teknei.acabus.core.entities.NavigationParent;
import com.teknei.acabus.core.entities.Role;
import com.teknei.acabus.core.facade.NavigationFacade;

/**
 * Singleton for storing utility values for Navigation purposes. Loads at startup
 * 
 * @author Jorge Amaro
 * @version 1.0
 * @since 1.0
 *
 */
@Startup
@Singleton
public class NavigationSingleton {

	private List<NavigationParent> listParent;
	private List<NavigationChild> listChilds;
	private Map<NavigationParent, List<NavigationChild>> map;
	private List<Role> listRoles;
	
	private static final Logger LOG = LoggerFactory.getLogger(NavigationSingleton.class);
	
	@EJB
	private NavigationFacade facadeNavigation;
	
	/**
	 * Initializing method. Stores all the navigation parents and childs in a Map
	 */
	@PostConstruct
	private void init(){
		map = new HashMap<NavigationParent, List<NavigationChild>>();
		try {
			listParent = facadeNavigation.findNavigationParents();
			for (NavigationParent parent : listParent) {
				listChilds = facadeNavigation.findNavigationChilds(parent.getIdParent());
				map.put(parent, listChilds);
			}
			listRoles = facadeNavigation.findRoles();
		} catch (FacadeException e) {	
			throw new RuntimeException();
		}
	}
	
	/**
	 * Looks for the root navigation item and its children
	 * @return the NavigationParent and its children in a {@code Map} instance
	 */
	public Map<NavigationParent, NavigationChild> findRootNavigation(){
		Map<NavigationParent, NavigationChild> returnMap = new HashMap<NavigationParent, NavigationChild>();
		Set<NavigationParent> parents = map.keySet();
		for(NavigationParent parent : parents){
			if(parent.getRoot() == 1){
				returnMap.put(parent, null);
				return returnMap;
			}
		}
		return returnMap;
	}
	
	/**
	 * Finds the current navigation item based on the URL
	 * @param url
	 * @return the Map instance with NavigationParent and children
	 */
	public Map<NavigationParent, NavigationChild> findNavigation(String url){
		if(url.equals("/")){
			return findRootNavigation();
		}
		Map<NavigationParent, NavigationChild> returnMap = new HashMap<NavigationParent, NavigationChild>();
		Set<NavigationParent> parents = map.keySet();
		for(NavigationParent parent : parents){
			if(parent.getUrl().equals(url)){
				returnMap.put(parent, new NavigationChild());
				return returnMap;
			}
		}
		for(NavigationParent parent : parents){
			List<NavigationChild> childs = map.get(parent);
			for(NavigationChild child : childs){
				if(child.getUrl().equals(url)){
					returnMap.put(parent, child);
					return returnMap;
				}
			}
		}
		returnMap.put(null, null);
		return returnMap;
	}
		
	
	/**
	 * @return the listParent
	 */
	public List<NavigationParent> getListParent() {
		return listParent;
	}
	/**
	 * @param listParent the listParent to set
	 */
	public void setListParent(List<NavigationParent> listParent) {
		this.listParent = listParent;
	}
	/**
	 * @return the listChilds
	 */
	public List<NavigationChild> getListChilds() {
		return listChilds;
	}
	/**
	 * @param listChilds the listChilds to set
	 */
	public void setListChilds(List<NavigationChild> listChilds) {
		this.listChilds = listChilds;
	}
	/**
	 * @return the facadeNavigation
	 */
	public NavigationFacade getFacadeNavigation() {
		return facadeNavigation;
	}
	/**
	 * @param facadeNavigation the facadeNavigation to set
	 */
	public void setFacadeNavigation(NavigationFacade facadeNavigation) {
		this.facadeNavigation = facadeNavigation;
	}

	/**
	 * @return the listRoles
	 */
	public List<Role> getListRoles() {
		return listRoles;
	}

	/**
	 * @param listRoles the listRoles to set
	 */
	public void setListRoles(List<Role> listRoles) {
		this.listRoles = listRoles;
	}
	
}
